/**
 * 
 */
package com.tongzhan.base;

import org.bson.Document;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.NoRepositoryBean;

import java.util.List;

/**
 * @author mintonzhang 2018年10月15日
 */
@NoRepositoryBean
public interface IBaseRepository<T, ID> extends MongoRepository<T, ID> {


	/**
	 * 按照条件和分页查询数据
	 * 
	 * @param query
	 * @param pageRequest
	 *            是 Pageable 的子类 提供了快速构建方法
	 */
	Page<T> findAll(Query query, PageRequest pageRequest);

	/**
	 * 按照条件和分页查询数据
	 *
	 * @param query
	 * @param pageRequest
	 *            是 Pageable 的子类 提供了快速构建方法
	 */
	Page<T> findPage(Query query, PageRequest pageRequest);

	/**
	 * 修改 逻辑删除也是调用这个方法
	 * 
	 * @param query
	 * @param update
	 */
	long updateOne(Query query, Update update);

	/**
	 * 修改多个
	 * 
	 * @param query
	 * @param update
	 */
	long updateMulti(Query query, Update update);

	/**
	 * 按照条件删除
	 * 
	 * @param query
	 */
	long delete(Query query);

	/**
	 * 根据主键id 删除某个实体类 注意：实体类的主键id必须加 @Primary 注解
	 *
	 * @param id
	 */
	long deletePrimaryKey(String id);

	/**
	 * 获取mongoTempalte
	 */
	MongoTemplate getMongotemplate();

	/**
	 * 
	 * 查询单个字段(替换之前的子查询) BaseCriteria 提供模糊查询区间段查询notnull 和isNotNull相关方法
	 * 
	 * @param criteria
	 *            查询条件语句
	 * @param field
	 *            要查询的字段
	 */
	List<Object> findSingleField(Criteria criteria, String field);

	List<T> findFields(Criteria criteria, String... field);

	/**
	 * 根据条件查询并排序
	 *
	 * @param query
	 * @return
	 */
	List<T> findAll(Query query);

	/**
	 * 按照id查询
	 * 
	 * @param id
	 *            id的key
	 * @param value
	 *            value
	 */
	T findById(String id, Object value);

	/**
	 * 根据主键id 查找某个实体类 注意：实体类的主键id必须加 @Primary 注解
	 * 
	 * @param id
	 */
	T findByPrimaryKey(String id);

	/**
	 * 按照条件查询一个对象
	 * 
	 * @param query
	 */
	T findOne(Query query);

	/**
	 * 查询总条数
	 * 
	 * @param query
	 */
	long count(Query query);

	/**
	 * 配合buliderPage 使用
	 * 
	 * @param query
	 * @param pageRequest
	 */
	List<T> find(Query query, PageRequest pageRequest);

	/**
	 * 配合find使用
	 * 
	 * @param list
	 * @param query
	 * @param pageRequest
	 */
	Page<T> buliderPage(List<T> list, Query query, PageRequest pageRequest);

	/**
	 * 查询某个字段 与findSingleF相似
	 * 
	 * @param query
	 * @param field
	 */
	List<Object> findSingleQuery(Query query, String field);
	

	/**
	 * 可变添加
	 * @param model
	 * @return
	 * 2018年10月27日
	 * @author  
	 */
	long insertSelective(T model);
	
	
	/**
	 * 可变修改
	 * @param model
	 * @return
	 * 2018年10月27日
	 * @author  
	 */
	long updateByPrimaryKeySelective(T model);

	long updateByPrimaryKey(T model);

    /**
     * 逻辑删除
     * @param model
     * @return
     */
	long logicDelete(T model);


    /**
     * 聚合函数  只能查询一个字段
     * @param match where 条件
     * @param key 要分组的字段
     * @param value 要聚合的字段
     * @param output 输出对象的类型
     * @param type 是需要 sum 还是count 等等
     * @param <O>
     * @return
     */
	<O> O group(Criteria match, String key, String value, Class<O> output, GroupType type);

	/**
	 * 根据字段统计
	 * @return
	 */
	List<Document> groupCount(Criteria match, String key);
}
